/* ---------------------------------------------------------------------------
** main.cpp
** Main file for a client that sends an unordered list of data to a server
** and receives a sorted list back
**
** Build Instructions:  Build and launch order have been set in solution properites
** Hit F7 to build solution, then F5 to run it.  Server and client will launch in their
** own separate windows.
**
** Author:	Patrick Montgomery
** Course:	SE 558
** Date:	Oct 6th, 2009
** -------------------------------------------------------------------------*/

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib,"ws2_32.lib")

#include "../SerializerLib/Serializer.h"
#include "TestData.h"
using namespace std;


int main(void)
{
	//--------------------------------------------------------
	// Get initialize data
	//--------------------------------------------------------
	TestData  data;
	list<int> &rNodeList = data.getNodeList();

	//--------------------------------------------------------
	// Print the original data
	//--------------------------------------------------------
	printf("\n\nClient: Original List\n\n");
	int j(0);
	for (list<int>::iterator it=rNodeList.begin(); it!=rNodeList.end(); ++it)
	{
		printf("    i:%d  %d\n",j++,*it);
	}

	//--------------------------------------------------------
	// Add your code and hooks here:
	//--------------------------------------------------------

	WSADATA wsaData;
	PCSTR SERVER_PORT = "16667";
	PCSTR SERVER_IP = "127.0.0.1";
	SOCKET ConnectSocket = INVALID_SOCKET;
	struct addrinfo hints;
	struct addrinfo *result = NULL;
	const int BUF_SIZE = ((rNodeList.size()+1) * sizeof(int));
	int bytesRecv = 0;
	int bytesSent = 0;
	char* buffer = new char[BUF_SIZE];
	

	// Initialize Winsock
	if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
	{
		std::cout << "WSAStartup failed.\n";
		return 1;
	}

	ZeroMemory( &hints, sizeof(hints) );
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	if (getaddrinfo(SERVER_IP, SERVER_PORT, &hints, &result) != 0)
	{
		std::cout << "getaddrinfo failed.\n";
		WSACleanup();
		return 1;
	}

	// Attempt to connect to the first address returned by
	// the call to getaddrinfo

	// Create a SOCKET for connecting to server
	ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

	if (ConnectSocket == INVALID_SOCKET) 
	{
		std::cout << "Socket creation failed.\n";
		freeaddrinfo(result);
		WSACleanup();
		return 1;
	}


	std::cout << "Client initialized.  Connecting to server...\n";
	if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) 
	{
		closesocket(ConnectSocket);
		ConnectSocket = INVALID_SOCKET;
	}
	

	freeaddrinfo(result);

	if (ConnectSocket == INVALID_SOCKET) {
		std::cout << "Unable to connect to server.  Goodbye!\n";
		WSACleanup();
		return 1;
	}
	else
		std::cout << "Connected!\n";

	//Marshall the list
	Serializer<int>::marshallList(rNodeList, buffer);

	//Send it to the server
	bytesSent = send( ConnectSocket, buffer, BUF_SIZE, 0 );
    if (bytesSent == SOCKET_ERROR) {
        printf("send() failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

	
    printf("Bytes Sent: %d\n", bytesSent);

	//Close the client's half of the connection
	if (shutdown(ConnectSocket, SD_SEND) == SOCKET_ERROR) {
		printf("shutdown failed: %d\n", WSAGetLastError());
		closesocket(ConnectSocket);
		WSACleanup();
		return 1;
	}

	// Zero out the buffer
	memset(buffer, 0, BUF_SIZE);

	// Receive until the peer closes the connection
    do {
        bytesRecv = recv(ConnectSocket, buffer, BUF_SIZE, 0);
        if ( bytesRecv > 0 )
            printf("Bytes received: %d\n", bytesRecv);
        else if ( bytesRecv == 0 )
            printf("Connection closed.\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

    } while( bytesRecv > 0 );

	//Unmarshall the results
	Serializer<int>::unmarshallList(buffer, rNodeList);

	delete buffer;
	closesocket(ConnectSocket);
	WSACleanup();


	//--------------------------------------------------------
	// Print the sorted data
	//--------------------------------------------------------
	printf("\n\nClient: Sorted List from the server\n\n");
	int k(0);
	for (list<int>::iterator it=rNodeList.begin(); it!=rNodeList.end(); ++it)
	{
		printf("    i:%d  %d\n",k++,*it);
	}
	printf("\n\n");
	system("PAUSE");
	

	return 0;
}